﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_Logger.h".
//-------------------------------------------------------------------

#include "CLogger.h"
#include "CLogFileOutput.h"
#include "COutputMessages.h"
//#include "CConsoleOutput.h"
#include "CVSConsoleOutput.h"

#ifndef _UXS_STD_CONSOLE_DISABLED
#include "CStdConsoleOutput.h"
#endif

namespace UX_STL
{
namespace UXLogger
{
	
#ifdef _UXS_STL_CONFIGURATION_H
	ILogger *	_s_pLogger	= null;
#endif
	
/*
=================================================
	конструктор
=================================================
*/
	CLogger::CLogger():
		_eFlagFilter(e_log_msg::FILTER_ALL),
		_eWarningLevel(e_log_msg::LEVEL_ALL),
		_uErrors(0), _uWarnings(0)
	{
		// init global variables
#	ifdef _UXS_STL_CONFIGURATION_H
		ASSERT( _s_pLogger == null );
		_s_pLogger = this;
#	endif

		SetWarningFilter( 15 );
	}
	
/*
=================================================
	деструктор
=================================================
*/
	CLogger::~CLogger()
	{
#	ifdef _UXS_STL_CONFIGURATION_H
		ASSERT( _s_pLogger == this );
		_s_pLogger = null;
#	endif

		FreeAll();
	}
	
/*
=================================================
	деструктор
=================================================
*/
	void CLogger::SetCallback(const CallbackProc_t &sOnFatalError)
	{
		_sOnFatalError = sOnFatalError;
	}

/*
=================================================
	создать объекты вывода сообщений
=================================================
*/
	bool CLogger::Create(e_log_output::bits eBits, const char *pLogFileName)
	{
		// Log File //
		if ( EnumCmp( eBits, e_log_output::LOG_FILE_BIT ) )
		{
			static const char	s_aDefaultLogFileName[] = "log.txt";

			if ( pLogFileName == null )
				pLogFileName = s_aDefaultLogFileName;
			
			HddWFilePtr	file = File::HddWFile::New();

			CHECK_ERR( file->Open( pLogFileName ) );

			if ( FileAddressUtils::GetExtension( (uni_c_string)pLogFileName ).ICmp( "html" ) )
			{
				Attach( new CHtmlLogOutput( file ) );
			}
			else
			{
				Attach( new CTxtLogOutput( file ) );
			}
		}

		// Message //
		if ( EnumCmp( eBits, e_log_output::MESSAGE_BIT ) )
		{
			Attach( new COutputMessages() );
		}

		// Console //
#	ifndef _UXS_STD_CONSOLE_DISABLED
		if ( EnumCmp( eBits, e_log_output::CONSOLE_BIT ) )
		{
			CStdConsoleOutput *	p_console = new CStdConsoleOutput();

			if ( p_console->Create() )
				Attach( p_console );
			else
				delete p_console;
		}
#	endif // _UXS_STD_CONSOLE_DISABLED

		// IDE Console //
		if ( EnumCmp( eBits, e_log_output::IDE_CONSOLE_BIT ) )
		{
			Attach( new CVSConsoleOutput() );
		}

		return true;
	}

/*
=================================================
	присоединить объект вывода сообщений
=================================================
*/
	void CLogger::Attach(ILogOutput *pOutput)
	{
		Detach( pOutput );
		_aOutput.PushBack( pOutput );
	}
	
/*
=================================================
	отсоединить объект вывода сообщений
=================================================
*/
	void CLogger::Detach(ILogOutput *pOutput)
	{
		FOR( i, _aOutput )
		{
			if ( _aOutput[i] == pOutput )
			{
				_aOutput.FastErase( i );
				return;
			}
		}
	}
	
/*
=================================================
	удалить все объекты вывода сообщений
=================================================
*/
	void CLogger::FreeAll()
	{
		FOR( i, _aOutput ) {
			_aOutput[i]->Free();
		}

		_aOutput.Clear();
	}
	
/*
=================================================
	записать в лог добавляя имя файла и номер строки
=================================================
*/
	void CLogger::WriteExt(const char *pMsg, e_log_msg::type eType, const char *pSrcFile, uint uLine)
	{
		if ( (eType & e_log_msg::_LWL_MASK) <= _eWarningLevel /*and
			 EnumNoCmp( eType, _eFlagFilter )*/ )	// TODO
		{
			for (usize i = 0; i < _aOutput.Count(); ++i)
				_aOutput[i]->Write( pMsg, eType, pSrcFile, uLine );
			
			switch ( eType & e_log_msg::_LMP_MASK )
			{
				case e_log_msg::_LMP_WARNING :	++_uWarnings;				break;
				case e_log_msg::_LMP_ERROR	 :	++_uErrors;					break;
				case e_log_msg::_LMP_FATAL	 :	_sOnFatalError.SafeCall();	break;
			}
		}
	}

//-------------------------------------------------------------------

}	// UXLogger
}	// UX_STL